#!/usr/bin/perl
use strict;
use FindBin;
use Cwd qw(abs_path);
use Getopt::Long;
use IO::Socket::INET;
use JSON;

sub usage {
    my $pname = $FindBin::Script;
    print("$pname --targetstatus <up|down> --host <host> --port <port>  --retrycount <retry count> --timeout <timeout seconds> .\n");
    exit(-1);
}

sub main {
    $| = 1;    #不对输出进行buffer，便于实时看到输出日志

    my ( $host, $port );
    my $targetStatus = 'up';
    my $retryCount   = 1;
    my $timeout      = 10;

    GetOptions(
        'targetstatus=s' => \$targetStatus,
        'host=s'         => \$host,
        'port=i'         => \$port,
        'retrycount=i'   => \$retryCount,
        'timeout=i'      => \$timeout
    );

    my $hasOptErr = 0;

    if ( not defined($host) or $host eq '' ) {
        $hasOptErr = 1;
        print("ERROR: Must defined host by option --host\n");
    }

    if ( not defined($port) or $port eq '' ) {
        $hasOptErr = 1;
        print("ERROR: Must defined port by option --port\n");
    }

    if ( $hasOptErr == 1 ) {
        usage();
    }

    my $isFailed = 1;

    if ( $targetStatus eq 'up' ) {
        for ( my $i = 1 ; $i <= $retryCount ; $i++ ) {
            print("INFO: Try to connect to $host:$port.\n");
            my $startTime = time();
            eval {
                my $socket = IO::Socket::INET->new(
                    PeerHost => $host,
                    PeerPort => $port,
                    Timeout  => $timeout
                );

                if ( defined($socket) ) {
                    $isFailed = 0;
                    print("INFO: Connect to $host:$port success.\n");
                    last;
                }
                else {
                    my $errMsg = "Connect to $host:$port failed, $!\n";
                    print("WARN: $errMsg");
                    my $leftTime = $timeout - ( time() - $startTime );
                    if ( $leftTime > 0 ) {
                        sleep($leftTime);
                    }
                }
            };
            if ($@) {
                my $errMsg = $@;
                $errMsg =~ s/ at\s*.*$//;
                print("ERROR: $errMsg");
                my $leftTime = $timeout - ( time() - $startTime );
                if ( $leftTime > 0 ) {
                    sleep($leftTime);
                }
            }
        }

        if ( $isFailed == 0 ) {
            print("FINE: Wait service $host:$port up succeed.\n");
        }
        else {
            print("ERROR: Wait service $host:$port up failed(timeout).\n");
        }
    }
    else {
        for ( my $i = 1 ; $i <= $retryCount ; $i++ ) {
            print("INFO: Try to connect to $host:$port.\n");
            my $startTime = time();
            eval {
                my $socket = IO::Socket::INET->new(
                    PeerHost => $host,
                    PeerPort => $port,
                    Timeout  => $timeout
                );

                if ( defined($socket) ) {
                    print("INFO: Connect to $host:$port success.\n");
                    my $leftTime = $timeout - ( time() - $startTime );
                    if ( $leftTime > 0 ) {
                        sleep($leftTime);
                    }
                }
                else {
                    $isFailed = 0;
                    print("INFO: Connect to $host:$port failed, $!\n");
                    last;
                }
            };
            if ($@) {
                my $errMsg = $@;
                $errMsg =~ s/ at\s*.*$//;
                print("ERROR: $errMsg");
                last;
            }
        }

        if ( $isFailed == 0 ) {
            print("FINE: Wait service $host:$port down success.\n");
        }
        else {
            print("ERROR: Wait service $host:$port down failed(timeout).\n");
        }
    }

    return $isFailed;
}

exit main();
